package com.xyoto.community.service.impl;

import com.github.pagehelper.PageHelper;
import com.xyoto.community.constant.*;
import com.xyoto.community.dto.GetQuestionCommentDTO;
import com.xyoto.community.dto.SaveQuestionCommentDTO;
import com.xyoto.community.entity.comment.QuestionComment;
import com.xyoto.community.entity.main.Message;
import com.xyoto.community.entity.main.Question;
import com.xyoto.community.enums.*;
import com.xyoto.community.exception.ExceptionUtils;
import com.xyoto.community.mapper.comment.QuestionCommentMapper;
import com.xyoto.community.mapper.comment.QuestionCommentReplyMapper;
import com.xyoto.community.mapper.main.MessageMapper;
import com.xyoto.community.mapper.main.QuestionMapper;
import com.xyoto.community.po.QuestionCommentPO;
import com.xyoto.community.po.QuestionCommentReplyPo;
import com.xyoto.community.po.UserPO;
import com.xyoto.community.service.*;
import com.xyoto.community.utils.JwtUtils;
import com.xyoto.community.utils.PageUtils;
import com.xyoto.community.utils.Result;
import com.xyoto.community.vo.QuestionCommentReplyVo;
import com.xyoto.community.vo.QuestionCommentsVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 * @author lin
 */
//@Service
@Slf4j
public class QuestionCommentServiceImpl implements QuestionCommentService {

    @Autowired
    private QuestionCommentReplyLoveService questionCommentReplyLoveService;

    @Autowired
    private QuestionCommentLoveService questionCommentLoveService;

    @Autowired
    private QuestionCommentReplyService questionCommentReplyService;

    @Autowired
    private UserService userService;

    @Resource
    private HttpServletRequest httpServletRequest;

    @Resource
    private QuestionMapper questionMapper;

    @Resource
    private QuestionCommentMapper questionCommentMapper;

    @Resource
    private MessageMapper messageMapper;

    @Resource
    private QuestionCommentReplyMapper questionCommentReplyMapper;



    /**
     * 新增问答评论
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public Result saveQuestionComment(SaveQuestionCommentDTO dto) {

        // 获取自己的id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);

        // 查询问答是否存在
        Question question = questionMapper.selectOneByQuestionId(dto.getQuestionId());
        if (question == null || question.getDeleteStatus() == DeleteStatus.YES){
            // 评论不存在或已删除
            ExceptionUtils.error(QuestionsEnum.QUESTIONS_IS_NULL);
        }

        // 新增问答评论
        QuestionComment questionComment = new QuestionComment();
        questionComment.setQuestionId(question.getId());
        questionComment.setContent(dto.getContent());
        questionComment.setDeleteStatus(DeleteStatus.NO);
        questionComment.setUserId(userId);
        Integer insertQuestionCommentCount = questionCommentMapper.insertQuestionComment(questionComment);
        if (insertQuestionCommentCount < 1){
            log.error("用户：{}，保存问答评论错误：{}",userId,questionComment);
            ExceptionUtils.error(QuestionsEnum.QUESTIONS_COMMENT_FAILED);
        }
        // 添加到消息通知总表
        Message message = new Message();
        //todo 少了目标用户的id
        message.setUserId(userId);
        message.setModuleId(questionComment.getId());
        message.setType(ModuleType.QUESTION_COMMENT);
        message.setReadStatus(ReadStatus.UNREAD);
        Integer insertNoticeCount = messageMapper.insertMessage(message);
        if (insertNoticeCount < DatabaseOperationResult.SUCCESS){
            log.error("用户：{}，保存通知错误：{}",userId,message);
            ExceptionUtils.error(LeaveMessageEnum.CREATE_LEAVE_MESSAGE_FAIL);
        }
        // 返回结果
        return Result.success();
    }

    /**
     * 根据问答id分页查询问答评论列表
     *
     * @param queryDto 分页查询问答评论列表DTO
     *
     * @return Result<PageUtils<QuestionCommentsVo>>
     */
    @Override
    public Result<PageUtils<QuestionCommentsVo>> getQuestionCommentsListById(GetQuestionCommentDTO queryDto){
        log.info("=====开始查询问答评论列表=====");

        // 返回list
        List<QuestionCommentsVo> questionCommentsVoList = new ArrayList<QuestionCommentsVo>();

        PageHelper.startPage(queryDto.getPageDTO().getPageNum(), queryDto.getPageDTO().getPageSize());

        // 查询父级评论部分信息
        List<QuestionCommentPO> questionCommentPoList = questionCommentMapper
                .getQuestionCommentsListById(queryDto.getQuestionId(), queryDto.getPageDTO().getEndIndexId());
        if (questionCommentPoList.size() == 0){
            ExceptionUtils.error(QuestionsEnum.QUESTION_COMMENTS_NOT_EXIST);
        }

        // 遍历父级评论部分信息查询用户信息
        for (QuestionCommentPO item : questionCommentPoList){
            QuestionCommentsVo questionCommentsVo = new QuestionCommentsVo();
            Integer parentId = item.getId();
            // 查询用户
            UserPO userPo = userService.getUserPartInfoById(item.getUserId());
            if (userPo == null){
                ExceptionUtils.error(QuestionsEnum.QUESTION_COMMENTS_NOT_EXIST);
            }
            questionCommentsVo.setId(parentId);
            questionCommentsVo.setAvatar(userPo.getAvatarUrl());
            questionCommentsVo.setNickname(userPo.getNickname());
            questionCommentsVo.setContent(item.getContent());
            questionCommentsVo.setCreateTime(item.getCreateTime());
            // 查询父级评论点赞数
            Integer parentCount = questionCommentLoveService.getQuestionCommentsLoveCountById(parentId);
            questionCommentsVo.setCommentLoveCount(parentCount);

            // 查询子级评论
            List<QuestionCommentReplyPo> replyVos =  questionCommentReplyService.getQuestionCommentReply(parentId);

            // 子级list
            List<QuestionCommentReplyVo> replyVoList = new ArrayList<>();
            // 遍历子级查询用户
            for (QuestionCommentReplyPo replyVo : replyVos){
                QuestionCommentReplyVo commentReplyVo = new QuestionCommentReplyVo();
                Integer childId = replyVo.getId();
                // 查询用户
                UserPO replyUserVo = userService.getUserPartInfoById(replyVo.getUserId());
                commentReplyVo.setId(childId);
                commentReplyVo.setAvatar(replyUserVo.getAvatarUrl());
                commentReplyVo.setNickname(replyUserVo.getNickname());
                commentReplyVo.setContent(replyVo.getContent());
                commentReplyVo.setCreateTime(replyVo.getCreateTime());
                // 查询评论回复点赞数
                Integer count = questionCommentReplyLoveService.getQuestionCommentReplyLoveCount(childId);
                commentReplyVo.setReplyLoveCount(count);
                replyVoList.add(commentReplyVo);
            }
            questionCommentsVo.setReplyDetailsList(replyVoList);
            questionCommentsVoList.add(questionCommentsVo);
        }

        log.info("=====结束查询问答评论列表=====");
        return new Result<>(CommonEnum.SUCCESS, PageUtils.restPage(questionCommentsVoList));
    }

    /**
     * 删除问答评论
     *
     * @param questionCommentId 问答id
     * @return
     */
    @Override
    @Transactional
    public Result removeQuestionComment(Integer questionCommentId) {
        if (null == questionCommentId || questionCommentId <= 0) {
            ExceptionUtils.error(QuestionsEnum.QUESTIONS_COMMENT_ID_ERROR);
        }
        //todo 检验权限 管理员权限未加
        //此条问答主人、此问答评论主人以及管理员可删此回复，其余用户不可删
        //校验问答评论是否存在
        QuestionComment questionComment = questionCommentMapper
                .getQuestionCommentById(questionCommentId);
        checkQuestionCommentExist(questionComment);
        //获取此问答评论主人id
        Integer questionCommentUserId = questionComment.getUserId();
        //检验问答是否存在
        Question question = questionMapper
                .getQuestionById(questionComment.getQuestionId());
        checkQuestionExist(question);
        //获取此问答评论主人id
        Integer questionUserId = question.getUserId();
        //获取当前用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        //判断权限
        if (!userId.equals(questionCommentUserId)
                || !userId.equals(questionUserId)) {
            ExceptionUtils.error(QuestionsEnum.NOT_POWER);
        }
        QuestionComment newQuestionComment = new QuestionComment();
        newQuestionComment.setDeleteStatus(DeleteStatus.YES);
        newQuestionComment.setUserId(userId);
        newQuestionComment.setId(questionCommentId);
        //删除评论
        Integer state = questionCommentMapper
                .removeQuestionComment(newQuestionComment);
        if (state != OperationStatus.SUCCESS) {
            ExceptionUtils.error(QuestionsEnum.DELETE_QUESTION_COMMENT_REPLY_FAILED);
        }
        Message message = new Message();
        message.setModuleId(questionCommentId);
        message.setType(ModuleType.QUESTION_COMMENT);
        message.setThirdParentId(question.getId());
        Integer newState = messageMapper.removeMessage(message);
        if (newState != OperationStatus.SUCCESS) {
            ExceptionUtils.error(MessageEnum.DELETED_QUESTION_COMMENT_MESSAGE_FAILED);
        }
        List<Integer> questionCommentReplyIdList = questionCommentReplyMapper
                .getQuestionCommentReplyListByQuestionCommentId(questionCommentId);
        if (null != questionCommentReplyIdList) {
            for (Integer replyId : questionCommentReplyIdList) {
                //删除回复消息
                Message newMessage = new Message();
                newMessage.setUserId(userId);
                newMessage.setType(ModuleType.QUESTION_COMMENT_REPLY);
                newMessage.setModuleId(replyId);
                newMessage.setThirdParentId(question.getId());
                Integer newStatus = messageMapper.removeMessage(newMessage);
                if (newStatus != OperationStatus.SUCCESS) {
                    ExceptionUtils.error(MessageEnum.DELETED_QUESTION_COMMENT_REPLY_MESSAGE_FAILED);
                }
            }
        }
        return Result.success();
    }

    /**
     * 检查问答是否存在或已经被逻辑删除
     * @param question
     */
    private void checkQuestionExist(Question question) {
        if (null == question){
            ExceptionUtils.error(QuestionsEnum.QUESTIONS_IS_NULL);
        }
        if (question.getDeleteStatus().equals(DeleteStatus.YES)){
            ExceptionUtils.error(QuestionsEnum.QUESTIONS_IS_DELETE);
        }
    }

    /**
     * 检查问答评论是否存在或已经被逻辑删除
     * @param questionComment
     */
    private void checkQuestionCommentExist(QuestionComment questionComment) {
        if (null == questionComment) {
            ExceptionUtils.error(QuestionsEnum.QUESTIONS_COMMENT_NOT_EXISTED);
        }
        if (questionComment.getDeleteStatus().equals(DeleteStatus.YES)) {
            ExceptionUtils.error(QuestionsEnum.QUESTIONS_COMMENT_IS_DELETE);
        }
    }
}
